package com.vegetable.modules.service.stock.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vegetable.common.async.AsyncStockService;
import com.vegetable.common.utils.Constant.StockFlowType;
import com.vegetable.common.utils.PageUtils;
import com.vegetable.common.utils.Query;
import com.vegetable.modules.entity.baseData.Products;
import com.vegetable.modules.entity.inbound.AgentDelivery;
import com.vegetable.modules.entity.inbound.AgentDeliveryDetailPack;
import com.vegetable.modules.entity.outbound.SalesOrderDetail;
import com.vegetable.modules.entity.outbound.SalesOrderDetailStock;
import com.vegetable.modules.entity.stock.Stock;
import com.vegetable.modules.entity.stock.po.StockQueryPO;
import com.vegetable.modules.entity.stock.po.StockUpdatePO;
import com.vegetable.modules.entity.stock.to.StockCostChangeDTO;
import com.vegetable.modules.entity.stock.CostAllocationRecord;
import com.vegetable.modules.mapper.stock.StockCostChangeMapper;
import com.vegetable.modules.mapper.stock.StockFlowMapper;
import com.vegetable.modules.mapper.stock.StockMapper;
import com.vegetable.modules.service.inbound.IAgentDeliveryDetailPackService;
import com.vegetable.modules.service.inbound.IPackDeliveryService;
import com.vegetable.modules.service.outbound.ISalesOrderDetailService;
import com.vegetable.modules.service.outbound.ISalesOrderDetailStockService;
import com.vegetable.modules.service.outbound.ISalesOutService;
import com.vegetable.modules.service.stock.ICostAllocationService;
import com.vegetable.modules.service.stock.IStockCostChangeService;
import com.vegetable.modules.service.stock.IStockFlowService;
import com.vegetable.modules.service.stock.IStockService;
import com.vegetable.common.annotation.StockAlertCheck;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 库存表 服务实现类
 * </p>
 *
 * @author wangruijie
 * @since 2024-03-21
 */
@Slf4j
@Service
public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements IStockService {
    @Resource
    private ISalesOutService salesOutService;
    @Lazy
    @Resource
    private IPackDeliveryService packDeliveryService;
    @Resource
    private StockFlowMapper stockFlowMapper;
    @Resource
    private IStockFlowService iStockFlowService;
    @Resource
    private AsyncStockService asyncStockService;
    @Resource
    private StockCostChangeMapper stockCostChangeMapper;
    @Lazy
    @Resource
    private IStockCostChangeService stockCostChangeService;
    @Resource
    private ISalesOrderDetailService iSalesOrderDetailService;
    @Resource
    private ISalesOrderDetailStockService iSalesOrderDetailStockService;
    @Resource
    private IAgentDeliveryDetailPackService detailPackService;
    @Resource
    private ICostAllocationService costAllocationService;
    /**
     * 库存列表查询
     * @param po
     * @return
     */
    @Override
    public PageUtils queryPage(StockQueryPO po) {
        QueryWrapper<Stock> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ObjectUtil.isNotNull(po.getId()), "id", po.getId());
        queryWrapper.between(ObjectUtil.isNotNull(po.getStartTime()) && ObjectUtil.isNotNull(po.getEndTime()), "order_time", po.getStartTime(), po.getEndTime());
        // 品名
        queryWrapper.like(StrUtil.isNotBlank(po.getCommodityName()), "commodity_name", po.getCommodityName());
        queryWrapper.like(StrUtil.isNotBlank(po.getAgentName()), "agent_name", po.getAgentName());
        queryWrapper.eq(StrUtil.isNotBlank(po.getCategory()), "category", po.getCategory());
        queryWrapper.eq(StrUtil.isNotBlank(po.getStockBatchNo()), "stock_batch_no", po.getStockBatchNo());
        // 标签
        queryWrapper.eq(ObjectUtil.isNotNull(po.getTag()), "tag", po.getTag());
        queryWrapper.eq(ObjectUtil.isNotNull(po.getCommodityId()), "commodity_id", po.getCommodityId());
        queryWrapper.eq(ObjectUtil.isNotNull(po.getSpecsId()), "specs_id", po.getSpecsId());
        if(po.getValidStock()){
            queryWrapper.and((wrapper) -> {
                wrapper.gt("number", 0).or().gt("weight", 0);
            });
        }

        if(StrUtil.isNotBlank(po.getCommodityName())){
            queryWrapper.last("order BY CASE     WHEN commodity_name = '"+po.getCommodityName()+"' THEN 1    " +
                    "WHEN commodity_name LIKE '"+po.getCommodityName()+"%' THEN 2    " +
                    "WHEN commodity_name LIKE '%"+po.getCommodityName()+"' THEN 3    " +
                    "WHEN commodity_name LIKE '%"+po.getCommodityName()+"%' THEN 4    ELSE 5    " +
                    "END, commodity_name, standard, agent_name");
        }else{
            queryWrapper.orderByDesc("commodity_id");
        }
        IPage<Stock> page = this.page(new Page(po.getPage(), po.getLimit()) , queryWrapper);
        if(CollectionUtil.isNotEmpty(page.getRecords())){
            List<Stock> stocks = page.getRecords();
            for(Stock stock : stocks){
                try {
                    String packageCost = stock.getPackageCost();
                    List<AgentDeliveryDetailPack> array = JSONArray.parseArray(packageCost, AgentDeliveryDetailPack.class);
                    if(CollectionUtil.isNotEmpty(array)){
                        stock.setPackageCostForSales(array.stream().mapToDouble(flow -> NumberUtil.mul(flow.getUnitPrice(), flow.getStandardNumber()).doubleValue()).sum());
                    }

                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
        return new PageUtils(page);
    }

    /**
     * 查询分组商品库存列表
     * @param params
     * @return
     */
    @Override
    public PageUtils stockGroupBy(Map<String, Object> params) {
        IPage iPage =  new Query<AgentDelivery>().getPage(params);
        IPage<Stock> page = baseMapper.stockGroupBy(iPage, params);
        return new PageUtils(page);
    }

    @Override
    public List<Stock> stockList(Long commodityId) {
        Wrapper<Stock> queryWrapper = new QueryWrapper<Stock>()
                        .eq("commodity_id", commodityId)
                        .and((wrapper) -> {
                            wrapper.gt("number", 0).or().gt("weight", 0);
                        })
                        .orderByDesc("order_time");
        List<Stock> orderCosts = this.getBaseMapper().selectList(queryWrapper);
        return orderCosts;
    }

    @Override
    public List<Stock> stockList(List<Long> commodityIds) {
        Wrapper<Stock> queryWrapper = new QueryWrapper<Stock>()
                .in(CollectionUtil.isNotEmpty(commodityIds),"commodity_id", commodityIds)
                .and((wrapper) -> {
                    wrapper.gt("number", 0).or().gt("weight", 0);
                })
                .orderByDesc("order_time");
        List<Stock> orderCosts = this.getBaseMapper().selectList(queryWrapper);
        return orderCosts;
    }

    @Override
    public IPage<Stock> stockList(StockQueryPO po) {
        return null;
    }

    /**
     * 1. 修改库存数量
     * 2. 写入库存流水
     * @param po
     * @return
     */
    @Override
    @Transactional
    @StockAlertCheck(value = "库存更新后预警检查", enabled = true)
    public Integer updateStock(StockUpdatePO po) throws Exception {
        Stock stock = baseMapper.selectById(po.getId());
        if(ObjectUtil.isNull(stock)){
            throw new Exception("库存不存在，请刷新页面重试");
        }
        BigDecimal changeNum;
        if(NumberUtil.equals(stock.getStandard(), BigDecimal.ZERO)){
            changeNum = NumberUtil.sub(po.getWeight(), stock.getWeight()).abs();
        }else{
            changeNum = NumberUtil.sub(po.getNumber(), stock.getNumber()).abs();
        }
        // 现有数量
        Integer nowNum = stock.getNumber();
        // 修改后的数量
        Integer updateNum = po.getNumber();
        // 1. 修改库存数量/库存总成本
        Stock update = new Stock();
        BeanUtils.copyProperties(po, update);
        // 如果标重商品，需要同时修改商品数量
        if(!NumberUtil.equals(BigDecimal.ZERO, stock.getStandard())){
            BigDecimal nowWeight = NumberUtil.mul(updateNum, stock.getStandard());
            update.setWeight(nowWeight);
        }else{
            // 如果是非标产品，则直接使用传入的weight
        }
        BigDecimal cost = stock.getCostWeight().multiply(new BigDecimal(updateNum));
        update.setCost(cost);
        log.info("修改商品数量，原数量：{} 现数量：{}", updateNum, nowNum);
        boolean res = updateById(update);
        if(!res){
            throw new OptimisticLockingFailureException("库存跟新失败，请刷新页面重试");
        }
        StockFlowType orderType = getStockFlowType(nowNum, updateNum, po.getUpdateType());
        // 2. 写入库存流水
        int flowRes = iStockFlowService.addStockFlow(stock, orderType.getValue(), changeNum, stock.getStorageOrderNo(), orderType.getName(), new Date());
        if(flowRes != 1){
            throw new Exception("库存流水写入失败，请刷新页面重试");
        }
//        // 开始重新计算走货的成本
//        log.info("{}更新库存，影响出库单成本", JSONObject.toJSONString(po));
//        salesOutService.checkOrderCostByStockId(stock.getId());
//        log.info("{}更新库存，影响加工单成品成本", JSONObject.toJSONString(po));
//        packDeliveryService.checkOrderCostByStockId(stock.getId());
        return flowRes;
    }

    private StockFlowType getStockFlowType(Integer nowNum, Integer updateNum, Integer updateType) {
        StockFlowType inType = updateType == 0 ? StockFlowType.INVENTORY_IN : StockFlowType.SALE_RETURN_IN;
        StockFlowType outType = updateType == 0 ? StockFlowType.INVENTORY_OUT : StockFlowType.SALE_OUT;
        StockFlowType orderType = updateNum > nowNum ? inType : outType;
        return orderType;
    }
    @Override
    public void updatePackageUnitPriceByDetailId(List<AgentDeliveryDetailPack> array, Long detailId, Long orderId) throws Exception {
        List<Stock> stocks = queryStockByDetailIdAndOrderId(orderId, detailId);
        if(CollectionUtil.isNotEmpty(stocks)){
            for(Stock stock : stocks){
                // 计算包装单价
                BigDecimal packageUnitPrice = calculatePackageUnitPriceByPackageCost(array);
                // 差价
                BigDecimal priceDifference = NumberUtil.sub(packageUnitPrice, stock.getPackageUnitPrice());
                // 判断包装价格是否发生变化
                if(NumberUtil.equals(priceDifference, BigDecimal.ZERO)){
                    continue;
                }
                Stock updater = new Stock();
                updater.setId(stock.getId());
                updater.setPackageUnitPrice(packageUnitPrice);

                boolean res = updateById(updater);
                if(!res){
                    throw new OptimisticLockingFailureException("库存跟新失败，请刷新页面重试");
                }
                // 开始重新计算走货的成本
                salesOutService.checkOrderCostByStockId(stock.getId());
                packDeliveryService.checkOrderCostByStockId(stock.getId());
            }
        }else{
            log.info("根据orderId:{}, detailId{}无法找到相应的库存", orderId, detailId);
        }
    }

    @Override
    public void updateStockByDetailId(BigDecimal nowCostWeight, Long detailId, Long orderId, BigDecimal goodsUnitPrice) throws Exception {
        List<Stock> stocks = queryStockByDetailIdAndOrderId(orderId, detailId);
        if(CollectionUtil.isNotEmpty(stocks)){
            // 处理所有库存，无论是原始库存还是衍生库存
            // 在订单价格变动时，所有相关库存都应使用相同的逻辑更新成本
            for(Stock stock : stocks){
                updateSingleStockCost(stock, nowCostWeight, goodsUnitPrice, detailId);
            }
        }else{
            log.info("根据orderId:{}, detailId{}无法找到相应的库存", orderId, detailId);
        }
    }
    
    /**
     * 更新单个库存的成本
     * @param stock 库存记录
     * @param nowCostWeight 新的成本单价
     * @param goodsUnitPrice 商品单价
     * @param detailId 明细ID
     * @throws Exception 异常
     */
    private void updateSingleStockCost(Stock stock, BigDecimal nowCostWeight, BigDecimal goodsUnitPrice, Long detailId) throws Exception {
        // 计算最终成本单价
        // 无论是原始库存还是衍生库存，在订单价格变动时都需要重新计算成本
        BigDecimal finalCostWeight = nowCostWeight;
        
        // 查询该库存相关的分摊记录
        List<CostAllocationRecord> allocationRecords = costAllocationService.getAllocationRecordsByStockId(stock.getId());
        
        // 计算分摊的总成本（仅计算直接更新类型的分摊）
        BigDecimal totalAllocatedCost = BigDecimal.ZERO;
        for (CostAllocationRecord record : allocationRecords) {
            // 如果是直接更新类型的分摊（原始库存ID等于分摊后库存ID），累加分摊成本
            if (record.getOriginalStockId() != null && record.getAllocatedStockId() != null 
                && record.getOriginalStockId().equals(record.getAllocatedStockId())) {
                // 获取分摊的成本差值（分摊后成本 - 分摊前成本）
                BigDecimal allocatedCost = NumberUtil.sub(record.getAfterCostWeight(), record.getBeforeCostWeight());
                totalAllocatedCost = NumberUtil.add(totalAllocatedCost, allocatedCost);
            }
        }
        
        // 合并新的成本和分摊成本
        finalCostWeight = NumberUtil.add(nowCostWeight, totalAllocatedCost);
        
        // 差价（使用最终成本计算差价）
        BigDecimal priceDifference = NumberUtil.sub(finalCostWeight, stock.getCostWeight());
        // 判断成本单价是否发生变化
        if(NumberUtil.equals(priceDifference, BigDecimal.ZERO)){
           return;
        }

        // 计算蔬菜单价和包装单价
        BigDecimal packageUnitPrice = BigDecimal.ZERO;
        
        // 获取包装费用信息
        List<AgentDeliveryDetailPack> array = detailPackService.selectByDetailId(detailId);
        if(CollectionUtil.isNotEmpty(array)){
            // 计算包装总费用
            BigDecimal packageCost = array.stream()
                .filter(flow -> flow.getMode() == 0)
                .map(AgentDeliveryDetailPack::getMoney)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
            
            // 计算包装单价（按重量分摊）
            if(stock.getWeight() != null && stock.getWeight().compareTo(BigDecimal.ZERO) > 0){
                packageUnitPrice = packageCost.divide(stock.getWeight(), 6, RoundingMode.HALF_UP);
            }
        }

        Stock updater = new Stock();
        updater.setId(stock.getId());
        updater.setCostWeight(finalCostWeight);  // 使用合并后的最终成本
        updater.setGoodsUnitPrice(goodsUnitPrice);
        updater.setPackageUnitPrice(packageUnitPrice);
        
        boolean res = updateById(updater);
        if(!res){
            throw new OptimisticLockingFailureException("库存更新失败，请刷新页面重试");
        }
        // 记录库存成本变化
        StockCostChangeDTO dto = new StockCostChangeDTO();
        BeanUtils.copyProperties(stock, dto);
        dto.setStockId(stock.getId());
        dto.setNowCost(stock.getCostWeight());
        List<Map<String, String>> detailList = new ArrayList<>();
        Map<String, String> detail = new HashMap<>();
        detail.put("蔬菜成本（按重）", updater.getCostWeight().toEngineeringString());

        if(CollectionUtil.isNotEmpty(array)){
            Double packageMoney = array.stream().filter(flow -> flow.getMode() == 0).mapToDouble(flow -> flow.getUnitPrice().doubleValue()).sum();
            detail.put("包装价格（按件）", packageMoney.toString());
        }
        detailList.add(detail);
        dto.setChangeCostDetailList(detailList);
        stockCostChangeService.add(dto);

        // 开始重新计算走货的成本
        salesOutService.checkOrderCostByStockId(stock.getId());
        packDeliveryService.checkOrderCostByStockId(stock.getId());
    }

    @Override
    @StockAlertCheck(value = "库存入库后预警检查", enabled = true)
    public void inStock(Date orderTime, BigDecimal cost, Products product,  Long specsId, String specsName,Integer inNumber, BigDecimal inWeight, Integer storageType , Long warehouseId, String warehouseName, String agentName, String packageCost, String storageOrderNo, Long orderId, Long detailId, BigDecimal goodsUnitPrice) {
        Stock stock = new Stock();
        stock.setCommodityId(product.getId());
        stock.setCommodityName(product.getCommonName());
        stock.setCommonCode(product.getCommonCode());
        stock.setCategory(product.getCategory());
        stock.setSpecsName(specsName);
        stock.setSpecsId(specsId);
        stock.setTag(product.getTags());
        stock.setStandard(product.getStandardWeight());
        stock.setOrderTime(orderTime);
        stock.setNumber(inNumber);
        stock.setInitNumber(inNumber);
        stock.setWeight(inWeight);
        stock.setInitWeight(inWeight);
        stock.setOrderId(orderId);
        stock.setDetailId(detailId);
        stock.setCost(cost);
        // 成本/重量
        BigDecimal costWeight = stock.getCost().divide(stock.getWeight(), 6, RoundingMode.HALF_UP);
        stock.setCostWeight(costWeight);
        

        
//        // 解析包装费用信息
        List<AgentDeliveryDetailPack> array = JSONArray.parseArray(packageCost, AgentDeliveryDetailPack.class);
//        if(CollectionUtil.isNotEmpty(array)){
//            // 计算包装总费用
//            BigDecimal packageCostTotal = array.stream()
//                .map(AgentDeliveryDetailPack::getMoney)
//                .reduce(BigDecimal.ZERO, BigDecimal::add);
//
//            // 计算包装单价（按重量分摊）
//            if(inWeight != null && NumberUtil.isGreater(inWeight, BigDecimal.ZERO)){
//                packageUnitPrice = packageCostTotal.divide(inWeight, 6, RoundingMode.HALF_UP);
//            }
//        }
        // 计算蔬菜单价和包装单价
        BigDecimal packageUnitPrice = calculatePackageUnitPriceByPackageCost(array);

        stock.setGoodsUnitPrice(goodsUnitPrice);
        stock.setPackageUnitPrice(packageUnitPrice);
        
        stock.setStorageType(storageType);
        stock.setStorageOrderNo(storageOrderNo);
        stock.setStockBatchNo(storageOrderNo);
        stock.setWarehouseId(warehouseId);
        stock.setWarehouseName(warehouseName);
        stock.setAgentName(agentName);
        stock.setPackageCost(packageCost);
        save(stock);
        BigDecimal changeNum = NumberUtil.equals(stock.getStandard(), BigDecimal.ZERO) ? stock.getWeight() : new BigDecimal(stock.getNumber());
        iStockFlowService.addStockFlow(stock, storageType, changeNum, stock.getStorageOrderNo(), "", orderTime);

        // 增加库存成本变化记录
        StockCostChangeDTO dto = new StockCostChangeDTO();
        BeanUtils.copyProperties(stock, dto);
        dto.setStockId(stock.getId());
        dto.setNowCost(stock.getCostWeight());
        List<Map<String, String>> detailList = new ArrayList<>();
        Map<String, String> detail = new HashMap<>();
        detail.put("蔬菜价格", cost.toEngineeringString());

        if(CollectionUtil.isNotEmpty(array)){
            Double packageMoney = array.stream().filter(flow -> flow.getMode() == 0).mapToDouble(flow -> flow.getMoney().doubleValue()).sum();
            detail.put("包装价格", packageMoney.toString());
        }
        detailList.add(detail);
        dto.setChangeCostDetailList(detailList);
        stockCostChangeService.add(dto);
        //
        asyncStockService.completeQuotation(stock.getCommodityId(), stock.getCostWeight(), orderTime, stock.getDetailId(), stock.getStorageType());
    }

    @Override
    @StockAlertCheck(value = "库存出库后预警检查", enabled = true)
    public void saveOutStock(BigDecimal price_unit, int outNumber, BigDecimal outWeight, Long stockId) throws Exception {
//        Stock stock = this.getBaseMapper().selectById(stockId);
//        if (stock != null){
//            int number = stock.getNumber() - outNumber;
//            BigDecimal weight = stock.getWeight().subtract(outWeight);
//            if (number > 0 && weight.compareTo(BigDecimal.ZERO) > 0){
//                stock.setWeight(weight);
//                stock.setNumber(number);
//                BigDecimal cost = stock.getCost();
//                cost = cost.add(price_unit.multiply(outWeight));
//                stock.setCost(cost);
//                // 成本/重量
//                BigDecimal costWeight = stock.getCost().divide(stock.getWeight(), 6, RoundingMode.HALF_UP);
//                stock.setCostWeight(costWeight);
//
//                // 更新蔬菜单价和包装单价（保持比例不变）
//                if (stock.getGoodsUnitPrice() != null && stock.getPackageUnitPrice() != null) {
//                    // 重新计算单价，保持原有比例
//                    BigDecimal totalUnitPrice = stock.getGoodsUnitPrice().add(stock.getPackageUnitPrice());
//                    if (totalUnitPrice.compareTo(BigDecimal.ZERO) > 0) {
//                        // 按原比例分配新的成本单价
//                        BigDecimal goodsRatio = stock.getGoodsUnitPrice().divide(totalUnitPrice, 6, RoundingMode.HALF_UP);
//                        BigDecimal packageRatio = stock.getPackageUnitPrice().divide(totalUnitPrice, 6, RoundingMode.HALF_UP);
//
//                        stock.setGoodsUnitPrice(costWeight.multiply(goodsRatio));
//                        stock.setPackageUnitPrice(costWeight.multiply(packageRatio));
//                    }
//                }
//
//                boolean res = updateById(stock);
//                if(!res){
//                    throw new OptimisticLockingFailureException("库存跟新失败，请刷新页面重试");
//                }
//                iStockFlowService.addStockFlow(stock, 7, outWeight, stock.getStorageOrderNo(), "销售出库", new Date());
//            }else{
//                // 数量为0 删除库存
//                this.getBaseMapper().deleteById(stockId);
//                iStockFlowService.addStockFlow(stock, 7, outWeight, stock.getStorageOrderNo(), "销售出库", new Date());
//            }
//        }
    }

    @Override
    public List<Stock> queryStockByOrderId(Long orderId) {
        QueryWrapper<Stock> query = new QueryWrapper<>();
        query.eq("order_id", orderId);
        return baseMapper.selectList(query);
    }
    
    @Override
    public List<Stock> queryStockByDetailId(Long detailId) {
        log.info("根据detailId查询库存记录，detailId: {}", detailId);
        QueryWrapper<Stock> query = new QueryWrapper<>();
        query.eq("detail_id", detailId);
        List<Stock> stocks = baseMapper.selectList(query);
        log.info("根据detailId {} 查询到 {} 条库存记录", detailId, stocks != null ? stocks.size() : 0);
        
        // 记录每条库存的详细信息
        if (stocks != null) {
            for (Stock stock : stocks) {
                log.debug("库存记录 - ID: {}, 商品名称: {}, 成本单价: {}, detailId: {}, orderId: {}", 
                    stock.getId(), stock.getCommodityName(), stock.getCostWeight(), stock.getDetailId(), stock.getOrderId());
            }
        }
        
        return stocks;
    }

    @Override
    public List<Stock> queryStockByDetailIdAndOrderId(Long orderId, Long detailId) {
        QueryWrapper<Stock> query = new QueryWrapper<>();
        query.eq("order_id", orderId);
        query.eq("detail_id", detailId);
        return baseMapper.selectList(query);
    }

    @Override
    public Stock queryStockByDetailIdAndOrderIdAndWarehouseId(Long orderId, Long detailId, Long warehouseId) {
        QueryWrapper<Stock> query = new QueryWrapper<>();
        query.eq("order_id", orderId);
        query.eq("detail_id", detailId);
        query.eq("warehouse_id", warehouseId);
        return baseMapper.selectOne(query);
    }

    @Override
    public List<Stock> queryDetailStock(Long detailId, boolean accurate, String commodityName, BigDecimal standard) {
//        List<Map<String, Object>> maps = new ArrayList<>();
        List<Stock> result = new ArrayList<>();
        SalesOrderDetail detail = iSalesOrderDetailService.getBaseMapper().selectById(detailId);
        if(ObjectUtil.isNotNull(detail)){
            // 商品库存
            List<Stock> stocks = getStocks(accurate, commodityName, standard, detail.getCommodityId(), detail.getSpecsId());
            // 已经走货库存
            List<Long> existIds = new ArrayList<>();
            List<SalesOrderDetailStock> detailStocks = iSalesOrderDetailStockService.selectByDetailId(detailId);
            if(CollectionUtil.isNotEmpty(detailStocks)){
                existIds = detailStocks.stream().map(d -> d.getStockId()).collect(Collectors.toList());
            }
            List<Long> finalExistIds = existIds;
            result = stocks.stream().
                    filter(ma -> (ma.getNumber() > 0 || NumberUtil.isGreater(ma.getWeight(), BigDecimal.ZERO)) || finalExistIds.contains(ma.getId())).
                    collect(Collectors.toList());
        }
        return result;
    }
    @Override
    public List<Stock> getStocks(boolean accurate, String commodityName, BigDecimal standard, Long commodityId, Long specsId) {
        QueryWrapper<Stock> queryWrapper = new QueryWrapper<>();
        if(accurate){
            queryWrapper.eq("commodity_id", commodityId);
            if(ObjectUtil.isNull(specsId)){
                queryWrapper.isNull("specs_id");
            }else {
                queryWrapper.eq("specs_id", specsId);
            }
        }else{
            if(StrUtil.isBlank(commodityName)){
                throw new RuntimeException("模糊查询库存时 商品名称不能为空");
            }
            queryWrapper.eq(StrUtil.isNotBlank(commodityName),"commodity_name", commodityName);
            queryWrapper.eq(!Objects.isNull(standard),"standard", standard);
        }
        queryWrapper.orderByAsc("order_time", "standard", "agent_name");
        // 该商品现有的库存
        List<Stock> stocks = baseMapper.selectList(queryWrapper);
        return stocks;
    }


    @Override
    public Stock selectById(Long stockId) {
        return this.baseMapper.selectById(stockId);
    }

    @Override
    public int deleteById(Long stockId) {
        return this.baseMapper.deleteById(stockId);    }

    @Override
    public List<Stock> selectGoodsStock(Long commodityId, Long specsId) {
        return selectGoodsStock(commodityId, specsId, null);
    }

    @Override
    public List<Stock> selectGoodsStock(List<Long> commodityIds) {
        QueryWrapper<Stock> queryWrapper = new QueryWrapper<Stock>()
                .in("commodity_id", commodityIds);
        queryWrapper.and(wrapper -> wrapper.gt("number", 0).or().gt("weight", BigDecimal.ZERO));
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public List<Stock> selectGoodsStock(Long commodityId, Long specsId, String agentName) {
        QueryWrapper<Stock> queryWrapper = new QueryWrapper<Stock>()
                .eq("commodity_id", commodityId);
        // 根据规格ID进行精确查询
        if(ObjectUtil.isNull(specsId)){
            queryWrapper.isNull("specs_id");
        }else {
            queryWrapper.eq("specs_id", specsId);
        }
        if(StrUtil.isNotBlank(agentName)){
            queryWrapper.eq("agent_name", agentName);
        }
        queryWrapper.and(wrapper -> wrapper.gt("number", 0).or().gt("weight", BigDecimal.ZERO));
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public List<Stock> selectStockByIds(List<Long> stockIds) {
        return this.baseMapper.selectBatchIds(stockIds);
    }

    @Override
    public void releaseStockByDetailId(Long detailId) throws Exception {
        List<SalesOrderDetailStock> detailStocks = iSalesOrderDetailStockService.selectByDetailId(detailId);
        if(CollectionUtil.isNotEmpty(detailStocks)){
            for(SalesOrderDetailStock detailStock : detailStocks){
                // 1. 删除该库存在销售出库单的使用情况
                iSalesOrderDetailStockService.deleteById(detailStock.getId());
                // 2. 恢复库存
                Stock nowStock = this.baseMapper.selectById(detailStock.getStockId());
                StockUpdatePO upPO = new StockUpdatePO();
                upPO.setId(detailStock.getStockId());
                upPO.setNumber(nowStock.getNumber() + detailStock.getNumber());
                upPO.setWeight(NumberUtil.add(nowStock.getWeight(), detailStock.getWeight()));
                upPO.setUpdateType(1);
                updateStock(upPO);
            }
        }
    }

    @Override
    public void releaseStockByDetailId(Long orderId, Long detailId, Integer orderType) throws Exception {
        // 查询该库存的使用情况
        List<SalesOrderDetailStock> detailStocks = iSalesOrderDetailStockService.selectList(orderId, detailId, orderType);
        if(CollectionUtil.isNotEmpty(detailStocks)){
            for(SalesOrderDetailStock detailStock : detailStocks){
                // 1. 删除该库存在销售出库单的使用情况
                iSalesOrderDetailStockService.deleteById(detailStock.getId());
                // 2. 恢复库存
                Stock nowStock = this.baseMapper.selectById(detailStock.getStockId());
                StockUpdatePO upPO = new StockUpdatePO();
                upPO.setId(detailStock.getStockId());
                upPO.setNumber(nowStock.getNumber() + detailStock.getNumber());
                upPO.setWeight(NumberUtil.add(nowStock.getWeight(), detailStock.getWeight()));
                upPO.setUpdateType(1);
                updateStock(upPO);
            }
        }
    }

    @Override
    public void releaseStockByDetailId2(Long detailId) throws Exception {
        // 2. 删除该库存在销售出库单的使用情况
        iSalesOrderDetailStockService.deleteByDetailId(detailId);
    }

    @Override
    public Map<Integer, BigDecimal> releaseStock(Stock stock) throws Exception {
        // 1. 返回已经处理完毕的数量跟重量
        Map<Integer, BigDecimal> result = new HashMap<>();
        // 查询该库存的使用情况
        List<SalesOrderDetailStock> detailStocks = iSalesOrderDetailStockService.selectByStockId(stock.getId());
        if(CollectionUtil.isNotEmpty(detailStocks)){
            Integer numSum = detailStocks.stream().mapToInt(e -> e.getNumber()).sum();
            BigDecimal weightSum = detailStocks.stream().map(e -> e.getWeight()).reduce(BigDecimal.ZERO, BigDecimal::add);
            result.put(0, new BigDecimal(numSum));
            result.put(1, weightSum);
        }
        // 2. 删除该库存在销售出库单的使用情况
        iSalesOrderDetailStockService.deleteByStockId(stock.getId());
        // 3. 删除库存
        this.getBaseMapper().deleteById(stock.getId());
        return result;
    }

    @Override
    public void releaseStock(Long orderId, Long detailId, Long warehouseId) throws Exception {
        releaseStock(orderId, detailId, warehouseId, true);
    }

    @Override
    public void releaseStock(Long orderId, Long detailId, Long warehouseId, boolean isDEl) throws Exception {
        Stock stock = queryStockByDetailIdAndOrderIdAndWarehouseId(orderId, detailId, warehouseId);
        if(ObjectUtil.isNull(stock)){
            return;
        }
        // 开始回收库存
        // 1. 释放销售走货占用的库存
        releaseStock(stock);
        // 2. 清空库存
        if(isDEl){
            baseMapper.deleteById(stock.getId());
        }else{
            StockUpdatePO downPO = new StockUpdatePO();
            downPO.setId(stock.getId());
            downPO.setNumber(0);
            downPO.setWeight(BigDecimal.ZERO);
            updateStock(downPO);
        }
    }

    @Override
    public void releaseStock(String storageOrderNo) {
        List<Stock> stocks = queryStock(storageOrderNo);
        // 删除销售走货占用的库存,同时删除库存
        if(CollectionUtil.isNotEmpty(stocks)){
            List<Long> stockIds = stocks.stream().map(el -> el.getId()).collect(Collectors.toList());
            for(Stock stock : stocks){
                iSalesOrderDetailStockService.deleteByStockId(stock.getId());
                deleteById(stock.getId());
            }
            stockCostChangeMapper.deleteByStockId(stockIds);
        }
        // 删除库存流水
        iStockFlowService.deleteByOrderNo(storageOrderNo);
    }

    @Override
    public List<Stock> queryStock(String docNo) {
        QueryWrapper<Stock> queryWrapper = new QueryWrapper<Stock>()
                .eq("storage_order_no", docNo);
        queryWrapper.and(wrapper -> wrapper.gt("number", 0).or().gt("weight", BigDecimal.ZERO));
        queryWrapper.orderByAsc("order_time");
        return this.baseMapper.selectList(queryWrapper);
    }
    
    @Override
    public List<Stock> getFinishedProductsWithOldOrderTime() {
        StockQueryPO po = new StockQueryPO();
        po.setLimit(Long.MAX_VALUE);
        po.setOverdueFinishedProduct(Boolean.TRUE);
        PageUtils pt = getFinishedProductsWithOldOrderTimeByConditionsPage(po);
        return (List<Stock>) pt.getList();
    }
    
    @Override
    public PageUtils getFinishedProductsWithOldOrderTimeByConditionsPage(StockQueryPO po) {
        // 如果是超期成品查询，修改查询条件
        if (po.getOverdueFinishedProduct() != null && po.getOverdueFinishedProduct()) {
            QueryWrapper<Stock> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("tag", 2); // 成品
            queryWrapper.lt("order_time", new Date(System.currentTimeMillis() - 2L * 24 * 60 * 60 * 1000)); // 超过两天
            queryWrapper.and((wrapper) -> {
                wrapper.gt("number", 0).or().gt("weight", 0);
            });
            // 添加其他筛选条件
            if (StrUtil.isNotBlank(po.getCategory())) {
                queryWrapper.eq("category", po.getCategory());
            }
            
            if (po.getStartTime() != null) {
                queryWrapper.apply("DATE(order_time) = DATE({0})", po.getStartTime());
            }
            
            if (StrUtil.isNotBlank(po.getAgentName())) {
                queryWrapper.like("agent_name", po.getAgentName());
            }
            
            if (StrUtil.isNotBlank(po.getCommodityName())) {
                queryWrapper.like("commodity_name", po.getCommodityName());
            }
            
            if (StrUtil.isNotBlank(po.getSpecsName())) {
                queryWrapper.like("specs_name", po.getSpecsName());
            }
            
            // 按超期时间倒序排列
            queryWrapper.orderByDesc("order_time");
            
            IPage<Stock> page = this.page(
                new Page<>(po.getPage(), po.getLimit()), 
                queryWrapper
            );
            
            return new PageUtils(page);
        } else {
            // 非超期成品查询，使用原有逻辑
            return queryPage(po);
        }
    }

    /**
     * 计算包装单价（按重均摊）
     * @param packs
     * @return
     */
    public BigDecimal calculatePackageUnitPriceByPackageCost(List<AgentDeliveryDetailPack> packs){
        BigDecimal result = BigDecimal.ZERO;
        if(CollectionUtil.isNotEmpty(packs)){
            for(AgentDeliveryDetailPack pack : packs){
                BigDecimal tmp = NumberUtil.mul(pack.getStandardNumber(), pack.getUnitPrice());
                result = NumberUtil.add(result, tmp);
            }
        }
        return result;
    }
    
    /**
     * 根据基础批次号查找相关库存记录
     * @param baseBatchNo 基础批次号
     * @return 相关库存记录列表
     */
    public List<Stock> findStocksByBaseBatchNo(String baseBatchNo) {
        if (baseBatchNo == null || baseBatchNo.isEmpty()) {
            return new ArrayList<>();
        }
        
        QueryWrapper<Stock> queryWrapper = new QueryWrapper<>();
        queryWrapper.likeRight("stock_batch_no", baseBatchNo);
        queryWrapper.orderByAsc("stock_batch_no");
        return this.list(queryWrapper);
    }

    @Override
    public IPage<Stock> getNonZeroStockWithCategory(IPage<Stock> page, Map<String, Object> params) {
        return baseMapper.getNonZeroStockWithCategory(page, params);
    }
    
}